package com.dpkit.processor;

import com.dpkit.adapter.orm.definition.AssociationDefinition;
import com.dpkit.adapter.orm.definition.EntityDefinition;
import com.dpkit.adapter.orm.definition.FieldDefinition;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 动态模板处理器
 * 负责将YAML/JSON模板转换为EntityDefinition
 */
public class DPKitTemplateProcessor {
    private final ObjectMapper yamlMapper;
    private final ObjectMapper jsonMapper;
    private final ResourceLoader resourceLoader;
    private final String templateLocation;
    private final ExpressionParser expressionParser = new SpelExpressionParser();

    public DPKitTemplateProcessor(ObjectMapper jsonMapper, 
                               ResourceLoader resourceLoader,
                               String templateLocation) {
        this.yamlMapper = new ObjectMapper(new YAMLFactory());
        this.jsonMapper = jsonMapper;
        this.resourceLoader = resourceLoader;
        this.templateLocation = templateLocation.endsWith("/") ? 
            templateLocation : templateLocation + "/";
    }

    /**
     * 从模板名称加载EntityDefinition
     */
    public EntityDefinition loadTemplate(String templateName) throws IOException {
        Resource resource = resourceLoader.getResource(templateLocation + templateName + ".yaml");
        try (InputStream is = resource.getInputStream()) {
            return yamlMapper.readValue(is, EntityDefinition.class);
        }
    }

    /**
     * 处理JSON数据并生成实体对象
     */
    public List<Object> process(String templateName, String jsonData) throws IOException {
        EntityDefinition definition = loadTemplate(templateName);
        JsonNode rootNode = jsonMapper.readTree(jsonData);
        
        // 获取输入数据（支持JSONPath）
        JsonNode inputData = rootNode.at(definition.getInputPath());
        if (!inputData.isArray()) {
            throw new IllegalArgumentException("Input data must be an array");
        }

        List<Object> entities = new ArrayList<>();
        for (JsonNode itemNode : inputData) {
            entities.add(processItem(itemNode, definition));
        }
        return entities;
    }

    /**
     * 处理单个数据项
     */
    private Object processItem(JsonNode itemNode, EntityDefinition definition) {
        StandardEvaluationContext context = new StandardEvaluationContext();
        context.setVariable("_source", jsonNodeToMap(itemNode));
        
        // 创建实体数据容器
        Map<String, Object> entityData = new HashMap<>();
        
        // 处理普通字段
        for (FieldDefinition field : definition.getFields().values()) {
            if (!field.isAssociation()) {
                Object value = evaluateExpression(field.getValueExpression(), context, field.getJavaType());
                entityData.put(field.getFieldName(), value);
            }
        }
        
        // 处理关联字段（需要先处理主实体）
        for (AssociationDefinition association : definition.getAssociations()) {
            Object assocValue = evaluateExpression(
                association.getValueExpression(), 
                context, 
                getAssociationType(association)
            );
            entityData.put(association.getFieldName(), assocValue);
        }
        
        return entityData;
    }

    /**
     * 执行SpEL表达式
     */
    private <T> T evaluateExpression(String expr, StandardEvaluationContext context, Class<T> type) {
        Expression expression = expressionParser.parseExpression(expr);
        return expression.getValue(context, type);
    }

    /**
     * 将JsonNode转换为Map便于SpEL处理
     */
    private Map<String, Object> jsonNodeToMap(JsonNode node) {
        Map<String, Object> result = new HashMap<>();
        Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
        
        while (fields.hasNext()) {
            Map.Entry<String, JsonNode> entry = fields.next();
            result.put(entry.getKey(), convertJsonValue(entry.getValue()));
        }
        return result;
    }

    /**
     * JsonNode值转换
     */
    private Object convertJsonValue(JsonNode node) {
        if (node.isTextual()) return node.asText();
        if (node.isNumber()) return node.numberValue();
        if (node.isBoolean()) return node.asBoolean();
        if (node.isArray()) {
            List<Object> list = new ArrayList<>();
            node.forEach(item -> list.add(convertJsonValue(item)));
            return list;
        }
        if (node.isObject()) return jsonNodeToMap(node);
        return null;
    }

    /**
     * 获取关联字段的Java类型
     */
    private Class<?> getAssociationType(AssociationDefinition association) {
        try {
            return Class.forName(association.getTargetEntity());
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("Target entity class not found: " + association.getTargetEntity(), e);
        }
    }
}